package com.sali.netty;

import com.sali.config.NettyConfig;
import com.sali.netty.handler.DecodeHandler;
import com.sali.netty.handler.ServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @description:
 * @author: sali
 * @date: 2025/2/22 下午10:32.
 * @version: 1.0
 */
@Slf4j
@Service
public class NettyService {

    @Autowired
    private NettyConfig nettyConfig;

    private NioEventLoopGroup bossGroup = null;
    private NioEventLoopGroup workerGroup = null;
    private Channel parentChannel;

    public void start() {
        if (nettyConfig.getBossGroup() != -1) {
            bossGroup = new NioEventLoopGroup(nettyConfig.getBossGroup());
        } else {
            bossGroup = new NioEventLoopGroup();
        }

        if (nettyConfig.getWorkerGroup() != -1) {
            workerGroup = new NioEventLoopGroup(nettyConfig.getWorkerGroup());
        } else {
            workerGroup = new NioEventLoopGroup();
        }

        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .option(ChannelOption.SO_BACKLOG, nettyConfig.getSocketQueue())
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline()
                                    .addLast(new DecodeHandler(65535, 1, 4, 0, 0))
                                    .addLast(new IdleStateHandler(30, 30, 90))
                                    .addLast(new ServerHandler());
                        }
                    })
                    .childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE);
            ChannelFuture f = bootstrap.bind(nettyConfig.getPort()).sync();
            parentChannel = f.channel();
            log.info("netty server running......");
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            log.error("netty server run is error,msg:[message:{}]", e.getMessage(), e);
            Thread.currentThread().interrupt();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public void destory() {
        log.info("开始关闭netty....");
        if (parentChannel != null) {
            parentChannel.close();
        }
        if (bossGroup != null) {
            bossGroup.shutdownGracefully();
        }
        if (workerGroup != null) {
            workerGroup.shutdownGracefully();
        }
        log.info("释放netty完毕");
    }

}
